/*
 * Copyright (c) 2013-2015 Isode Limited.
 * All rights reserved.
 * See the COPYING file for more information.
 */

#pragma once

#include <string>

#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/shared_ptr.hpp>

#include <QTextEdit>
#include <QWidget>

#include <Swift/Controllers/UIInterfaces/ChatWindow.h>

#include <Swift/QtUI/QtChatView.h>
#include <Swift/QtUI/QtChatWindow.h>

class QTextEdit;
class QProgressBar;

namespace Swift {
	class HighlightAction;
	class SecurityLabel;

	class QtPlainChatView : public QtChatView {
		Q_OBJECT
		public:
			QtPlainChatView(QtChatWindow *window, UIEventStream* eventStream);
			virtual ~QtPlainChatView();

			/** Add message to window.
			 * @return id of added message (for acks).
			 */
			virtual std::string addMessage(const ChatWindow::ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/);
			/** Adds action to window.
			 * @return id of added message (for acks);
			 */
			virtual std::string addAction(const ChatWindow::ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/);

			virtual std::string addSystemMessage(const ChatWindow::ChatMessage& /*message*/, ChatWindow::Direction /*direction*/);
			virtual void addPresenceMessage(const ChatWindow::ChatMessage& /*message*/, ChatWindow::Direction /*direction*/);
			virtual void addErrorMessage(const ChatWindow::ChatMessage& /*message*/);

			virtual void replaceMessage(const ChatWindow::ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/);
			virtual void replaceWithAction(const ChatWindow::ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/);
			virtual void replaceLastMessage(const ChatWindow::ChatMessage& /*message*/, const ChatWindow::TimestampBehaviour /*timestampBehaviour*/);
			virtual void replaceSystemMessage(const ChatWindow::ChatMessage& message, const std::string& id, const ChatWindow::TimestampBehaviour /*timestampBehaviour*/);
			virtual void setAckState(const std::string& /*id*/, ChatWindow::AckState /*state*/);

			virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/, const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/, const std::string& /*description*/);
			virtual void setFileTransferProgress(std::string, const int /*percentageDone*/);
			virtual void setFileTransferStatus(std::string, const ChatWindow::FileTransferState /*state*/, const std::string& /*msg*/ = "");
			virtual void addMUCInvitation(const std::string& /*senderName*/, const JID& /*jid*/, const std::string& /*reason*/, const std::string& /*password*/, bool /*direct*/, bool /*isImpromptu*/, bool /*isContinuation*/);
			virtual std::string addWhiteboardRequest(const QString& /*contact*/, bool /*senderIsSelf*/) {return "";};
			virtual void setWhiteboardSessionStatus(const std::string& /*id*/, const ChatWindow::WhiteboardSessionState /*state*/) {};
			virtual void setMessageReceiptState(const std::string& /*id*/, ChatWindow::ReceiptState /*state*/) {};

			virtual void showEmoticons(bool /*show*/) {};
			virtual void addLastSeenLine() {};

		public slots:
			virtual void resizeFont(int /*fontSizeSteps*/) {};
			virtual void scrollToBottom();
			virtual void handleKeyPressEvent(QKeyEvent* /*event*/) {};
			virtual void fileTransferAccept();
			virtual void fileTransferReject();
			virtual void fileTransferFinish();
			virtual void acceptMUCInvite();
			virtual void rejectMUCInvite();

		private:
			struct PopupDialog {
				PopupDialog(QtPlainChatView* parent) {
					dialog_ = new QFrame(parent);
					dialog_->setFrameShape(QFrame::Panel);
					dialog_->setFrameShadow(QFrame::Raised);
					layout_ = new QHBoxLayout;
					dialog_->setLayout(layout_);
				}
				virtual ~PopupDialog() {
					delete dialog_;
				}
				QFrame* dialog_;
				QHBoxLayout* layout_;
			};

			struct AcceptMUCInviteAction : public QPushButton {
				AcceptMUCInviteAction(PopupDialog* parent, const std::string& text, const JID& jid, const std::string& senderName, const std::string& password, bool isImpromptu, bool isContinuation)
				: QPushButton(P2QSTRING(text)), parent_(parent), jid_(jid), senderName_(senderName), password_(password), isImpromptu_(isImpromptu), isContinuation_(isContinuation) {}
				PopupDialog *parent_;
				JID jid_;
				std::string senderName_;
				std::string password_;
				bool isImpromptu_;
				bool isContinuation_;
			};

			struct FileTransfer : public PopupDialog {
				struct Action : QPushButton {
					Action(const std::string& text, const std::string& id)
					: QPushButton(P2QSTRING(text)), id_(id) {}
					std::string id_;
				};
				FileTransfer(QtPlainChatView* parent, bool senderIsSelf, const std::string& ftId, const std::string& filename, const ChatWindow::FileTransferState state, const std::string& desc, const std::string& msg, bool initializing);
				QProgressBar* bar_;
				bool senderIsSelf_;
				std::string ftId_;
				std::string filename_;
				std::string description_;
				std::string message_;
				bool initializing_;
			};

			class LogTextEdit : public QTextEdit {
			public:
				LogTextEdit(QWidget* parent) : QTextEdit(parent) {}
				virtual ~LogTextEdit() {}
				virtual void contextMenuEvent(QContextMenuEvent *event);
			};

			typedef std::map<std::string, FileTransfer*> FileTransferMap;
			QtChatWindow* window_;
			UIEventStream* eventStream_;
			LogTextEdit* log_;
			FileTransferMap fileTransfers_;
			std::map<std::string, boost::shared_ptr<SecurityLabel> > lastMessageLabel_;
			int idGenerator_;

	};
}
